package dmmm.components;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

public class GPR extends LogicalComponent {

	private Pin read;
	private Pin write;
	private ArrayList<Integer> regs;
	private int size;

	public GPR(int numOfRegisters, int sizeOfRegister) {
		super(2, 1, true);
		out[0].setIsInt();
		out[0].setNumOfLines(sizeOfRegister);
		size = numOfRegisters;
		regs = new ArrayList<Integer>(numOfRegisters);
		for (int i = 0; i < numOfRegisters; i++) {
			regs.add(0);
			// regs[i] = 0;
		}
		addSequentialComponent(this);
	}

	public void func() {
		if (write.getBoolVal()) {
			// da se ne bi snimala referenca na istu komponentu samo
			// i zato da se ne bi cuvala samo jedna memorija i samo jedan GPR
			// fajsl
			regs = new ArrayList<Integer>(regs);

			regs.set(in[0].getIntVal(), in[1].getIntVal());
		}
	}

	public void read() {
		if (read.getBoolVal()) {
			out[0].setIntVal(regs.get(in[0].getIntVal()), false);
		}
	}

	public void clear() {
		for (int i = 0; i < regs.size(); i++) {
			regs.set(i, 0);
		}
	}

	public int getSize() {
		return regs.size();
	}

	public void setRead(Pin read) {
		this.read = read;
		read.addChild(this);
	}

	public void setWrite(Pin write) {
		this.write = write;
		write.addChild(this);
	}

	public int getRegValue(int index) {
		return regs.get(index);
	}

	//ne koristi se vise nakon uvodjenja metode writeRtregVa
	public void setRegValue(int index, int value) {
		regs.set(index, value);
	}

	// ZA CUVANJE STANJA RADI POVRATKA UNAZAD

	// radi cuvanja - exp
	public void writeRegValue(int index, int value) {
		regs = new ArrayList<Integer>(regs);
		regs.set(index, value);
		if (read.getBoolVal() && (in[0].getIntVal() == index)) {
			out[0].setIntVal(regs.get(index), false);
		}
	}

	public State getState() {
		return new State(regs, out[0].getIntVal());
	}

	@SuppressWarnings("unchecked")
	public void restoreState(State state) {
		regs = (ArrayList<Integer>) state.innerState;
		out[0].setIntVal((Integer) state.outPin, false);
	}

	// ZA CUVANJE STANJA SIMUALACIJE U FAJL
	public void writeState(State state, PrintWriter writer) {
		@SuppressWarnings("unchecked")
		ArrayList<Integer> regs = (ArrayList<Integer>) state.innerState;
		for (int i = 0; i < regs.size(); i++) {
			if (regs.get(i) != 0) {
				writer.println("R" + i + ": " + regs.get(i));
			}
		}
		writer.println((Integer) state.outPin);
	}

	public void loadState(BufferedReader reader) {
		regs = new ArrayList<Integer>(size);
		for (int i = 0; i < size; i++) {
			regs.add(i, 0);
		}
		try {
			String reg = reader.readLine();
			while (reg.contains(":")) {
				String[] tokens = reg.split(":");
				writeRegValue(Integer.parseInt(tokens[0].substring(1)),
						Integer.parseInt(tokens[1].trim()));
				reg = reader.readLine();
			}
			out[0].setIntVal(Integer.parseInt(reg), false);
		} catch (IOException e) {
			System.out.println("Error reading save file!");
		}
	}
}
